home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / reve / boardstuff.c next >
C/C++ Source or Header  |  1995-05-03  |  21KB  |  806 lines

  1. /*LINTLIBRARY*/
  2.  
  3. /*  @(#)boardstuff.c 1.27 91/11/13
  4.  *
  5.  *  Various board routines used by reve.
  6.  *
  7.  *  Copyright (C) 1990, 1991 - Rich Burridge & Yves Gallot.
  8.  *  All rights reserved.
  9.  *
  10.  *  Permission is granted to copy this source, for redistribution
  11.  *  in source form only, provided the news headers in "substantially
  12.  *  unaltered format" are retained, the introductory messages are not
  13.  *  removed, and no monies are exchanged.
  14.  *
  15.  *  Permission is also granted to copy this source, without the
  16.  *  news headers, for the purposes of making an executable copy by
  17.  *  means of compilation, provided that such copy will not be used
  18.  *  for the purposes of competition in any othello tournaments, without
  19.  *  prior permission from the authors.
  20.  *
  21.  *  No responsibility is taken for any errors on inaccuracies inherent
  22.  *  either to the comments or the code of this program, but if reported
  23.  *  (see README file), then an attempt will be made to fix them.
  24.  */
  25.  
  26. #include "reve.h"
  27. #include "color.h"
  28. #include "extern.h"
  29. #include <ctype.h>
  30.  
  31. #ifdef X11
  32. #include <X11/Xos.h>
  33. #endif /*X11*/
  34.  
  35. void
  36. animate_move(move)
  37. int move ;
  38. {
  39.   int x0, y0, x1, y1, x, y, dx, dy, ctr ;
  40.  
  41.   lock_screen(IS_ON) ;
  42.   get_xy(move, &x1, &y1) ;
  43.   dx = x1 ;
  44.   dy = y1 ;
  45.   if (x1 > y1)
  46.     {
  47.       ctr = dx / 2 ;
  48.       x = bborder ;
  49.       y = bborder ;
  50.       draw_piece(WHITE, x, y, RINV) ;
  51.       while (x < x1)
  52.         {
  53. #ifndef SYSV
  54.           set_timer() ;
  55. #endif /*!SYSV*/
  56.           x0 = x ;
  57.           y0 = y ;
  58.           x += move_delta ;
  59.           if ((ctr -= dy) < 0)
  60.             {
  61.               ctr += dx ;
  62.               y += move_delta ;
  63.             }
  64.           draw_piece(WHITE, x, y, RINV) ;
  65.           draw_piece(WHITE, x0, y0, RINV) ;
  66. #ifndef SYSV
  67.           nap_upto(1) ;
  68. #endif /*!SYSV*/
  69.         }
  70.       draw_piece(WHITE, x, y, RINV) ;
  71.     }
  72.   else
  73.     { 
  74.       ctr = dy / 2 ;
  75.       x = bborder ;
  76.       y = bborder ;
  77.       draw_piece(WHITE, x, y, RINV) ;
  78.       while (y < y1)
  79.         {
  80. #ifndef SYSV
  81.           set_timer() ;
  82. #endif /*!SYSV*/
  83.           x0 = x ;
  84.           y0 = y ;
  85.           y += move_delta ;
  86.           if ((ctr -= dx) < 0)
  87.             {
  88.               ctr += dy ;
  89.               x += move_delta ;
  90.             }
  91.           draw_piece(WHITE, x, y, RINV) ;
  92.           draw_piece(WHITE, x0, y0, RINV) ;
  93. #ifndef SYSV
  94.           nap_upto(1) ;
  95. #endif /*!SYSV*/
  96.         }
  97.       draw_piece(WHITE, x, y, RINV) ;
  98.     }
  99.   lock_screen(IS_OFF) ;
  100. }
  101.  
  102.  
  103. /*  This routine checks to see if a move can be made for this player.
  104.  *  If not, various checks are made to see if the game is finished.
  105.  *  Return value indicates if a move can be made.
  106.  */
  107.  
  108. int
  109. check(player)
  110. int player ;
  111. {
  112.   if ((!count(&board, BLACK)) || (!count(&board, WHITE)) ||
  113.       ((count(&board, BLACK) + count(&board, WHITE)) == 64))
  114.     {
  115.       who_wins() ;
  116.       last_cmode = cmode ;     /* Save previous value in case of undo. */
  117.       cmode = GAME_OVER ;
  118.       message(PANEL_MES, "***GAME OVER***") ;
  119.       return(FALSE) ;
  120.     }
  121.   if ((move = valid_move(&board, player)) == FALSE)
  122.     {
  123.       SPRINTF(line, "%s is forced to pass",
  124.                     (player == BLACK) ? bstone_name : wstone_name) ;
  125.       message(PANEL_MES, line) ;
  126.       set_turn(OPPONENT(player)) ;
  127.       if ((move = valid_move(&board, OPPONENT(player))) == FALSE)
  128.         {
  129.           who_wins() ;
  130.           last_cmode = cmode ;
  131.           cmode = GAME_OVER ;
  132.           message(PANEL_MES, "***GAME OVER***") ;
  133.         }
  134.       return(FALSE) ;
  135.     }
  136.   return(TRUE) ;
  137. }
  138.  
  139.  
  140. int
  141. count(board, player)    /* Count the number of player pieces on the board. */
  142. BOARD *board ;
  143. int player ;
  144. {
  145.   int i, n ;
  146.  
  147.   n = 0 ;
  148.   FOR_BOARD(i)
  149.     if (board->square[i] == player) n++ ;
  150.   return(n) ;
  151. }
  152.  
  153.  
  154. void
  155. do_move(player)
  156. int player ;
  157. {
  158.   int taken ;                /* Number of pieces flipped this go. */
  159.  
  160.   taken = formfliplist(move, player) ;
  161.   update_board_image(player, taken) ;
  162. }
  163.  
  164.  
  165. void
  166. draw_outline(move, state)
  167. int move ;
  168. enum bltype state ;
  169. {
  170.   if (last_outline == -1) return ;
  171.   draw_square(move, state, 1) ;
  172. }
  173.  
  174.  
  175. void
  176. draw_piece(piece, x, y, op)    /* Draw an othello piece on the board. */
  177. int piece, x, y ;
  178. enum optype op ;
  179. {
  180.   switch (piece)
  181.     {
  182.       case BLACK : draw_stencil(W_BOARD, x, y,
  183.                                 2 * pieceXrad, 2 * pieceYrad, op,
  184.                                 B_COLOR(C_BSTONE), P_BLACK, P_BLACK) ;
  185.                    if (iscolor && op != RINV)
  186.                      draw_image(W_BOARD, x, y,
  187.                                 2 * pieceXrad, 2 * pieceYrad, P_WHITE) ;
  188.                    break ;
  189.       case WHITE : if (iscolor)
  190.                      {
  191.                        draw_stencil(W_BOARD, x, y,
  192.                                     2 * pieceXrad, 2 * pieceYrad, op,
  193.                                     C_WSTONE, P_BLACK, P_BLACK) ;
  194.                        if (op != RINV)
  195.                          draw_image(W_BOARD, x, y,
  196.                                     2 * pieceXrad, 2 * pieceYrad, P_WHITE) ;
  197.                      }
  198.                    else
  199.                      draw_stencil(W_BOARD, x, y,
  200.                                   2 * pieceXrad, 2 * pieceYrad, op,
  201.                                   C_WHITE, P_BLACK, P_WHITE) ;
  202.     }
  203. }
  204.    
  205.  
  206. void
  207. draw_rect(wtype, x1, y1, x2, y2, op, color)
  208. enum win_type wtype ;
  209. int x1, y1, x2, y2, color ;
  210. enum optype op ;
  211. {
  212.   draw_line(wtype, x1, y1, x2, y1, op, color) ;
  213.   draw_line(wtype, x1, y1, x1, y2, op, color) ;
  214.   draw_line(wtype, x2, y1, x2, y2, op, color) ;
  215.   draw_line(wtype, x1, y2, x2, y2, op, color) ;
  216. }
  217.  
  218.  
  219. void
  220. draw_square(move, state, offset)
  221. int move, offset ;
  222. enum bltype state ;
  223. {
  224.   int color, x, y ;
  225.  
  226.   if (state == IS_ON) color = C_BLACK ;
  227.   else                color = W_COLOR(C_SQUARE) ;
  228.  
  229.   x = (move & 7)  * cell_width + bborder ;
  230.   y = (move >> 3) * cell_height + bborder ;
  231.   draw_rect(W_BOARD, x + offset,              y + offset,
  232.                      x + cell_width - offset, y + cell_height - offset,
  233.                      RSRC, color) ;
  234. }
  235.  
  236.  
  237. void
  238. draw_symbol(image, n, state)
  239. enum image_type image ;
  240. int n ;
  241. enum bltype state ;
  242. {
  243.   int color, x, y ;
  244.  
  245.   if (state == IS_OFF) color = W_COLOR(C_SQUARE) ;
  246.   else                 color = C_BLACK ;
  247.  
  248.   x = bborder + ((n & 7)  + 1) * cell_width  - cell_width  / 2 ;
  249.   x -= (SWIDTH / 2) ;
  250.   y = bborder + ((n >> 3) + 1) * cell_height - cell_height / 2 ;
  251.   y -= (SHEIGHT / 2) ;
  252.  
  253.   if (state == IS_OFF)
  254.     color_area(W_BOARD, x, y, SWIDTH, SHEIGHT, W_COLOR(C_SQUARE)) ;
  255.   else
  256.     draw_stencil(W_BOARD, x, y, SWIDTH, SHEIGHT, RSRC, color, image, image) ;
  257.   if (state == IS_ON)
  258.     draw_image(W_BOARD, x, y, SWIDTH, SHEIGHT, image) ;
  259. }
  260.  
  261.  
  262. int
  263. formfliplist(move, player)
  264. int move, player ;
  265. {        
  266.   int cnt, i, n, old_cnt ;
  267.  
  268.   old_cnt = count(&board, player) ;
  269.   FOR_BOARD(i) old_board.square[i] = board.square[i] ;
  270.   old_board.moves_left = board.moves_left ;
  271.   domove(&old_board, move, &board, player) ;
  272.  
  273.   n = 63 - board.moves_left ;
  274.   FOR_BOARD(i) moves[n].square[i] = board.square[i] ;
  275.   moves[n].moves_left = board.moves_left ;
  276.   moves[n].move = move ;
  277.   moves[n].note = note ;
  278.   moves[n].player = player ;
  279.   moves[n].timeleft = timeleft ;
  280.  
  281.   cnt = count(&board, player) ;
  282.   return(cnt - old_cnt - 1) ;
  283. }
  284.  
  285.  
  286. void
  287. initboard()    /* Initialise the othello board. */
  288. {
  289.   static int ivals[4]   = { 27,    28,    35,    36 } ;
  290.   static int icolors[4] = { WHITE, BLACK, BLACK, WHITE } ;
  291.   int i, j , n ;
  292.  
  293.   suggestion = -1 ;
  294.   sstate     = IS_OFF ;
  295.   show_moves = FALSE ;
  296.   for (i = 0; i < 64; i++) moves[i].move = -1 ;
  297.   for (n = 0; n < 4; n++)
  298.     {
  299.       FOR_BOARD(i) moves[n].square[i] = FREE ;
  300.       for (j = 0; j <= n; j++) moves[n].square[ivals[j]] = icolors[j] ;
  301.       moves[n].player     = icolors[n] ;
  302.       moves[n].move       = ivals[n] ;
  303.       moves[n].moves_left = 63 - n ;
  304.     }
  305.  
  306.   FOR_BOARD(i) old_board.square[i] = board.square[i] = FREE ;
  307.   board.square[27] = WHITE ;
  308.   board.square[28] = BLACK ;
  309.   board.square[35] = BLACK ;
  310.   board.square[36] = WHITE ;
  311.   board.moves_left = 60 ;
  312. }
  313.  
  314.  
  315. void
  316. load_game()
  317. {
  318.  
  319. /*  Read in a game from file, and setup internal variables accordingly.
  320.  *
  321.  *  Notation in the games file is of the format:
  322.  *  1, <C-4>   -     [ remarks field ]
  323.  *  2,   -   <E-3>   [ remarks field ]
  324.  *
  325.  *  The move number is the field before the comma. This is just used as a
  326.  *  consistency check. Next is the black move or the white move (surronded
  327.  *  by '<' and '>' characters. Obviously only one piece moves per go, and
  328.  *  the '-' character is used to signify which piece doesn't move (in case
  329.  *  one player had to miss a turn.
  330.  *
  331.  *  As each position is added, the board is redisplayed, and if the game is
  332.  *  not over, the next player can commence.
  333.  */
  334.  
  335.   char buf[MAXLINE], col, *lptr, *mptr, row ;
  336.   int moveno, n ;
  337.   FILE *fp ;
  338.  
  339.   if ((fp = fopen(gamefile, "r")) == NULL)
  340.     {
  341.       SPRINTF(buf, "Couldn't open game file: %s", gamefile) ;
  342.       message(PANEL_MES, buf) ;
  343.       return ;
  344.     }
  345.  
  346.   moveno = 0 ;
  347.   initboard() ;
  348.   last_move = -1 ;
  349.   paint_board() ;
  350.   message(EVAL_MES, "") ;
  351.   while (fgets(buf, MAXLINE, fp) != NULL)
  352.     {
  353.       if (buf[0] == '\n' || buf[0] == '#') continue ;
  354.       moveno++ ;
  355.       SSCANF(buf, "%d", &n) ;
  356.       if (n != moveno || n > 60)
  357.         {
  358.           SPRINTF(buf, "Load error: incorrect move [%d] on line %d", n, move) ;
  359.           message(PANEL_MES, buf) ;
  360.           return ;
  361.         }
  362.       lptr = (char *) index(buf, '<') ;
  363.       mptr = (char *) index(buf, '-') ;
  364.       if (lptr == NULL || mptr == NULL)
  365.         {
  366.           SPRINTF(buf, "Load error: missing < or - on line %d", move) ;
  367.           message(PANEL_MES, buf) ;
  368.           return ;
  369.         }
  370.       if (lptr < mptr) next_player = BLACK ;    /* Black move? */
  371.       else             next_player = WHITE ;
  372.       SSCANF(lptr, "<%c-%c>", &row, &col) ;
  373.       if (load_move(row, col) == 0)
  374.         {
  375.           SPRINTF(buf, "Load error: invalid move <%c-%c> on line %d",
  376.                                     row, col, move) ;
  377.           message(PANEL_MES, buf) ;
  378.           return ;
  379.         }
  380.       SPRINTF(buf, "Loaded move %d for %s", moveno,
  381.                    (next_player == BLACK) ? bstone_name : wstone_name) ;
  382.       message(PANEL_MES, buf) ;
  383.     }
  384.   FCLOSE(fp) ;
  385.  
  386.   set_score() ;
  387.   set_turn(OPPONENT(next_player)) ;
  388.  
  389.   cmode = (enum cantype) (OPPONENT(next_player) + 1) ;
  390.   next_player = OPPONENT(next_player) ;
  391.  
  392.   if (check(next_player) == TRUE) return ;
  393.   cmode = (enum cantype) (OPPONENT(next_player) + 1) ;
  394.   next_player = OPPONENT(next_player) ;
  395.   if (check(next_player) == FALSE) return ;
  396.  
  397.   if ((next_player == BLACK && cmode == BLACK_START) ||
  398.       (next_player == WHITE && cmode == WHITE_START))
  399.     {
  400.       opponent_move(next_player) ;
  401.       next_player = OPPONENT(next_player) ;
  402.     }
  403. }
  404.  
  405.  
  406. int
  407. load_move(col, row)
  408. int col, row ;
  409. {
  410.   int i, x, y ;
  411.  
  412.   if (row < '1' || row > '8') return(0) ;
  413.   if (isupper(col))           col = tolower(col) ;
  414.   if (col < 'a' || col > 'h') return(0) ;
  415.   move = (row - '1') * BOARD_SIZE + (col - 'a') ;
  416.   if (legal(move, next_player, &board) == 0) return(0) ;
  417.   (void) formfliplist(move, next_player) ;
  418.   batch(IS_ON) ;
  419.   if (DO_LAST)   show_last(last_move, IS_OFF) ;
  420.   if (DO_NUMBER) show_number(last_move, 59 - board.moves_left, IS_OFF) ;
  421.   FOR_BOARD(i)
  422.     if (board.square[i] != old_board.square[i])
  423.       {
  424.         get_xy(i, &x, &y) ;
  425.         draw_piece(next_player, x, y, RSRC) ;
  426.       } 
  427.   if (DO_LAST)   show_last(move, IS_ON) ;
  428.   if (DO_NUMBER) show_number(move, 60 - board.moves_left, IS_ON) ;
  429.   last_move = move ;
  430.   batch(IS_OFF) ;
  431.   return(1) ;
  432. }
  433.  
  434.  
  435. #ifndef SYSV
  436. void
  437. nap_upto(n)          /* Sleep upto n microseconds from start of timer. */
  438. int n ;
  439. {
  440.   struct timeval ctp ;
  441.   struct timezone ctzp ;
  442.   long elapsed ;     /* Number of microseconds since timer started. */
  443.  
  444.   GETTIMEOFDAY(&ctp, &ctzp) ;
  445.   elapsed = ((ctp.tv_usec - tp.tv_usec) +
  446.             (ctp.tv_sec - tp.tv_sec) * 1000000L) / 1000 ;
  447.   if (elapsed > n) return ;
  448.   usleep((unsigned) (n - elapsed)) ;
  449. }
  450. #endif /*!SYSV*/
  451.  
  452.  
  453. void
  454. opponent_move(player)
  455. int player ;
  456. {
  457.   for (;;)
  458.     {
  459.       if (processing == FALSE)
  460.         {
  461.           if (check(player) == TRUE)
  462.             {
  463.               set_cursor(HOURGLASS) ;
  464.               best_cmove = -1 ;
  465.               message(EVAL_MES, "") ;
  466.               move = moves[63 - board.moves_left].move ;
  467.               reset_clock(player) ;
  468. #ifdef REMOTE_PLAYER
  469.               if (isremote) write_to_sock(socketfd, move) ;
  470.               else 
  471. #endif /* REMOTE_PLAYER */
  472.            write_to_reve(M_MOVE, board.square, player, level) ;
  473.               if (opp_iconise == TRUE) close_reve() ;
  474.               return ;
  475.             }
  476.           else
  477.             {
  478.               if (cmode != GAME_OVER)
  479.                 cmode = (enum cantype) ((int) cmode - 1) ;
  480.               next_player = OPPONENT(next_player) ;
  481.               return ;
  482.             }
  483.         }
  484.       else
  485.         {
  486.           processing = FALSE ;
  487.           update_clock(next_player, TRUE) ;
  488.           do_opponent_move(player) ;
  489.           reset_clock(OPPONENT(player)) ;
  490.           if (check(OPPONENT(player)) == TRUE || cmode == GAME_OVER)
  491.             {
  492.               next_player = OPPONENT(next_player) ;
  493.               if (opp_iconise == TRUE) open_reve() ;
  494.               if (opp_bell    == TRUE) beep() ;
  495.               if (opp_raise   == TRUE) raise_reve() ;
  496.               return ;
  497.             }
  498.         }    
  499.     }    
  500. }
  501.  
  502.  
  503. void
  504. print_game()
  505. {
  506.   char buf[MAXLINE] ;
  507.   FILE *fp ;
  508.  
  509.   if ((fp = popen(printcommand, "w")) == NULL)
  510.     {
  511.       SPRINTF(buf, "Couldn't open printer: %s", printcommand) ;
  512.       message(PANEL_MES, buf) ;
  513.       return ;
  514.     }
  515.   save_game_to(fp) ;
  516.   PCLOSE(fp) ;
  517.   SPRINTF(buf, "Current game printed on %s", printcommand) ;
  518.   message(PANEL_MES, buf) ;
  519. }
  520.  
  521.  
  522. void
  523. save_game_to(fp)
  524. FILE *fp ;
  525. {
  526.   int n ;
  527.  
  528.   for (n = 4; n < 64; n++)
  529.     {
  530.       if (moves[n].move == -1) break ;
  531.       if (moves[n].player == BLACK)
  532.         FPRINTF(fp, "%d,  <%c-%c>   -  [ note : %ld ]\n",
  533.                 n-3, (moves[n].move % 8)  + 'a',
  534.                      (moves[n].move >> 3) + '1', moves[n].note) ;
  535.       else
  536.         FPRINTF(fp, "%d,  -   <%c-%c>  [ note : %ld ]\n",
  537.                 n-3, (moves[n].move % 8)  + 'a',
  538.                      (moves[n].move >> 3) + '1', moves[n].note) ;
  539.     }
  540. }
  541.  
  542.  
  543. void
  544. save_game()
  545. {
  546.  
  547. /*  Save the current game status to file.
  548.  *
  549.  *  The notation in the saved games file is of the format:
  550.  *  1, <C-4>   -    [ note : 12345 ]
  551.  *  2,   -   <E-3>  [ note : 0 ]
  552.  *
  553.  *  The move number is the field before the comma. This is just used as a
  554.  *  consistency check. Next is the black move or the white move (surronded
  555.  *  by '<' and '>' characters. Obviously only one piece moves per go, and
  556.  *  the '-' character is used to signify which piece doesn't move (in case
  557.  *  one player had to miss a turn.
  558.  */
  559.  
  560.   char buf[MAXLINE] ;
  561.   FILE *fp ;
  562.  
  563.   if ((fp = fopen(gamefile, "w")) == NULL)
  564.     {
  565.       SPRINTF(buf, "Couldn't open game file: %s", gamefile) ;
  566.       message(PANEL_MES, buf) ;
  567.       return ;
  568.     }
  569.   save_game_to(fp) ;
  570.   FCLOSE(fp) ;
  571.   SPRINTF(buf, "Current game saved in %s", gamefile) ;
  572.   message(PANEL_MES, buf) ;
  573. }
  574.  
  575.  
  576. void
  577. set_eval(player, move, note)
  578. int player, move ;
  579. long note ;
  580. {
  581.   SPRINTF(line, "%s: <%c-%c> eval : %ld depth: %d",
  582.           (player == BLACK) ? bstone_name : wstone_name,
  583.           (move & 7) + 'a', (move >> 3) + '1', note, profmax) ;
  584.   message(EVAL_MES, line) ;
  585. }
  586.  
  587.  
  588. void
  589. set_score()
  590. {
  591.   SPRINTF(line, "Stones: %s: %2d  %s: %2d",
  592.                  bstone_name, count(&board, BLACK),
  593.                  wstone_name, count(&board, WHITE)) ;
  594.   message(SCORE_MES, line) ;
  595. }
  596.  
  597.  
  598. void
  599. set_turn(player)
  600. int player ;
  601. {
  602.   SPRINTF(line, "%s to move", (player == BLACK) ? bstone_name : wstone_name) ;
  603.   message(TURN_MES, line) ;
  604. }
  605.  
  606.  
  607. #ifndef SYSV
  608. void
  609. set_timer()
  610. {
  611.   struct timezone tzp ;
  612.  
  613.   GETTIMEOFDAY(&tp, &tzp) ;
  614. }
  615. #endif /*!SYSV*/
  616.  
  617.  
  618. void
  619. show_all(state)
  620. enum bltype state ;
  621. {
  622.   int count, i, player ;
  623.  
  624.   batch(IS_ON) ;
  625.   if (state == IS_ON)
  626.     {
  627.       FOR_BOARD(i) s_all.square[i] = FREE ;
  628.       FOR_BOARD(i)
  629.         if (board.square[i] == FREE &&
  630.             (count = legal(i, next_player, &board)) != 0)
  631.           {
  632.             s_all.square[i] = next_player ;
  633.             draw_symbol(S_MOVE, i, IS_ON) ;
  634.             show_number(i, count, IS_ON) ;
  635.           }
  636.     }
  637.   else
  638.     {
  639.       FOR_BOARD(i)
  640.         if (s_all.square[i] != FREE)
  641.           {
  642.             s_all.square[i] = FREE ;
  643.             draw_symbol(S_MOVE, i, IS_OFF) ;
  644.           }
  645.       if (suggestion != -1 && sstate == IS_ON)
  646.         {
  647.           player = (cmode == WHITE_START) ? WHITE : BLACK ;
  648.           do_suggest(player, suggestion, snote, IS_ON) ;
  649.         }
  650.     }    
  651.   batch(IS_OFF) ;
  652.   show_moves = (int) state ;
  653. }
  654.  
  655.  
  656. void
  657. show_best(move, note)
  658. int move ;
  659. long note ;
  660. {
  661.   batch(IS_ON) ;
  662.   if (move == -1 || DO_BESTMOVE == FALSE) return ;
  663.   if (best_cmove != -1)
  664.     {
  665.       draw_square(best_cmove, IS_OFF, 2) ;
  666.       if (DO_NUMBER) show_number(best_cmove, cmove_depth, IS_OFF) ;
  667.     }
  668.   best_cmove  = move ;
  669.   cmove_depth = profmax ;
  670.   draw_square(best_cmove, IS_ON, 2) ;
  671.   if (DO_NUMBER)  show_number(best_cmove, cmove_depth, IS_ON) ;
  672.   if (SHOW_NOTES) set_eval(next_player, move, note) ;
  673.   batch(IS_OFF) ;
  674. }
  675.  
  676.  
  677. void
  678. show_last(move, state)
  679. int move ;
  680. enum bltype state ;
  681. {
  682.   if (move == -1) return ;
  683.   if (board.moves_left < 60) draw_square(move, state, 2) ;
  684. }
  685.  
  686.  
  687. void
  688. show_number(move, val, state)
  689. int move, val ;
  690. enum bltype state ;
  691. {
  692.   char num[3] ;
  693.   int color, strw, x, y ;
  694.  
  695.   if (move == -1) return ;
  696.  
  697.        if (board.square[move] == BLACK)
  698.     color = (state == IS_ON) ? C_WHITE : B_COLOR(C_BSTONE) ;
  699.   else if (board.square[move] == WHITE)
  700.     color = (state == IS_ON) ? C_BLACK : W_COLOR(C_WSTONE) ;
  701.   else if (iscolor)
  702.     color = (state == IS_ON) ? C_BLACK : C_SQUARE ;
  703.   else
  704.     color = (state == IS_ON) ? C_BLACK : C_WHITE ;
  705.  
  706.   x = (move & 7)  * cell_width  + bborder + pieceXmargin ;
  707.   y = (move >> 3) * cell_height + bborder + pieceYmargin ;
  708.  
  709.   SPRINTF(num, "%2d", val) ;
  710.   strw = get_strwidth(GFONT, num) ;
  711.  
  712.   x = x + ((2 * pieceXrad) - strw) / 2 ;
  713.   if (val < 10) x -= 3 ;
  714.   y = y + font_heights[(int) GFONT] - 1 +
  715.       ((2 * pieceYrad) - font_heights[(int) GFONT]) / 2 ;
  716.   draw_text(W_BOARD, x, y, GFONT, color, num) ;
  717. }
  718.  
  719.  
  720. void
  721. update_board_image(player, taken)
  722. int player, taken ;
  723. {
  724.   update_pieces(player, taken) ;
  725.   last_move = move ;
  726.   if (SHOW_NOTES)
  727.     if ((player == BLACK && items[(int) BLACK_PLAYS].value == COMPUTER) ||
  728.         (player == WHITE && items[(int) WHITE_PLAYS].value == COMPUTER))
  729.       set_eval(player, move, note) ;
  730. }
  731.  
  732.  
  733. void
  734. update_pieces(player, taken)
  735. int player, taken ;
  736. {
  737.   int flips, i, piece, total_flips, x, y ;
  738.  
  739.   total_flips = (QUICKGAME) ? 2 : 4 ;
  740.   if (DO_LAST)   show_last(last_move, IS_OFF) ;
  741.   if (DO_NUMBER) show_number(last_move, 59 - board.moves_left, IS_OFF) ;
  742.  
  743.   if (show_moves || (invalid == TRUE && SHOW_LEGAL)) show_all(IS_OFF) ;
  744.   if (suggestion != -1) draw_symbol(S_SUGGEST, suggestion, IS_OFF) ;
  745.   suggestion = -1 ;
  746.   sstate     = IS_OFF ;
  747.   for (flips = 0; flips < total_flips; flips++)
  748.     {
  749.       batch(IS_ON) ;
  750.       FOR_BOARD(i)
  751.         {
  752.           if (board.square[i] != old_board.square[i])
  753.             {
  754.               get_xy(i, &x, &y) ;
  755.               if (i == move) piece = board.square[i] ;
  756.               else
  757.                 piece = (flips % 2) ? board.square[i] : board.square[i] * -1 ;
  758.               draw_piece(piece, x, y, RSRC) ;
  759.             } 
  760.         }    
  761.       batch(IS_OFF) ;
  762.       PAUSE ;
  763.     } 
  764.   if (DO_LAST)   show_last(move, IS_ON) ;
  765.   if (DO_NUMBER) show_number(move, 60 - board.moves_left, IS_ON) ;
  766.   set_score() ;
  767.   set_turn(OPPONENT(player)) ;
  768.   if (DO_LAST == FALSE && DO_NUMBER == FALSE)
  769.     SPRINTF(line, "%s moved at <%c-%c> and took %d %s",
  770.                   (player == BLACK) ? bstone_name : wstone_name,
  771.                   (move % 8)  + 'a', (move >> 3) + '1',
  772.                   taken, (taken  == 1)     ? "stone" : "stones") ;
  773.   else
  774.     SPRINTF(line, "%s took %d %s",
  775.                   (player == BLACK) ? bstone_name : wstone_name,
  776.                   taken, (taken  == 1)     ? "stone" : "stones") ;
  777.   message(PANEL_MES, line) ;
  778. }
  779.  
  780.  
  781. void
  782. who_wins()
  783. {
  784.   int cs, ps ;
  785.  
  786.   ps = count(&board, WHITE) ;
  787.   cs = count(&board, BLACK) ;
  788.   if (ps > cs)
  789.     {
  790.       SPRINTF(line, "%s wins %d-%d", wstone_name, ps, cs) ;
  791.       message(SCORE_MES, line) ;
  792.     }
  793.   else if (ps == cs)
  794.     {
  795.       SPRINTF(line,"A tie %d-%d", ps, cs) ;
  796.       message(SCORE_MES, line) ;
  797.     }
  798.   else
  799.     {
  800.       SPRINTF(line, "%s wins %d-%d", bstone_name, cs, ps) ;
  801.       message(SCORE_MES, line) ;
  802.     }
  803.   message(TURN_MES, "") ;
  804.   message(EVAL_MES, "") ;
  805. }
  806.